package cn.accjiyun.ca.controller;

import cn.accjiyun.ca.common.controller.BaseController;
import cn.accjiyun.ca.common.utils.DateUtils;
import cn.accjiyun.ca.entity.CAConfig;
import cn.accjiyun.ca.entity.UserPuk;
import cn.accjiyun.ca.security.RSAUtils;
import cn.accjiyun.ca.service.UserPukService;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.security.PrivateKey;
import java.util.Date;

/**
 * Created by jiyun on 2017/5/23.
 */
@Controller
@RequestMapping
public class CertificateController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(CertificateController.class);

    @Autowired
    private UserPukService userPukService;

    @RequestMapping("/generateCert/{userId}")
    @ResponseBody
    public String generateCert(@PathVariable("userId") int userId,
                               HttpServletRequest request, HttpServletResponse response) {

        UserPuk userPuk = userPukService.queryUserPukById(userId);
        if (userPuk != null) {
            return getReturnJson("该用户已经申请过证书！", 404);
        }
        String password = request.getParameter("password");
        if (password == null) {
           return getReturnJson("密码不能为空！", 404);
        }

        CAConfig caConfig = new CAConfig();
        caConfig.setCA_DEFAULT_SUBJECT(caConfig.getCA_DEFAULT_SUBJECT() + userId);
        caConfig.setPK_PASSWORD(password);
        String realPath = request.getServletContext().getRealPath("WEB-INF/certificate/") + File.separator
                + DateUtils.formatDate(new Date(), "yyyyMMdd");
        File realDir = new File(realPath);
        if (!realDir.exists()) realDir.mkdirs();
        String certPath = realPath + File.separator + System.currentTimeMillis();

        userPukService.generateCert(userId, caConfig, certPath);
        String pfxUrl = certPath + ".pfx";
        userPuk = new UserPuk();
        userPuk.setPfxUrl(pfxUrl);

        userPuk.setUserId(userId);
        String pukUrl = certPath + ".cer";
        userPuk.setPukUrl(pukUrl);
        userPukService.createUserPuk(userPuk);

        downloadFile(new File(pfxUrl), response);
        return null;
    }

    @RequestMapping("/getPukCert/{userId}")
    @ResponseBody
    public String getPukCert(@PathVariable("userId") int userId,
                               HttpServletRequest request, HttpServletResponse response) {
        UserPuk userPuk = userPukService.queryUserPukById(userId);
        if (userPuk == null) return getReturnJson("This user has not applied for the certificate!", 200);
        File cerFile = new File(userPuk.getPukUrl());
        downloadFile(cerFile, response);
        return null;
    }

    @RequestMapping("/getPfxCert/{userId}")
    @ResponseBody
    public String getPfxCert(@PathVariable("userId") int userId,
                             HttpServletRequest request, HttpServletResponse response) {
        UserPuk userPuk = userPukService.queryUserPukById(userId);
        String password = request.getParameter("password");
        if (userPuk == null) return getReturnJson("This user has not applied for the certificate!", 200);
        CAConfig caConfig = new CAConfig();
        caConfig.setPK_PASSWORD(password);
        PrivateKey privateKey = RSAUtils.readPKCS12(userPuk.getPfxUrl(), caConfig);
        if (privateKey == null) return getReturnJson("Authentication Failed!", 200);
        File pfxFile = new File(userPuk.getPfxUrl());
        downloadFile(pfxFile, response);
        return null;
    }

    public void downloadFile(File file, HttpServletResponse response) {
        if (file.exists()) {
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition", "attachment;fileName=" + file.getName());
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public String getReturnJson(String meg, int status) {
        JsonObject resultJson = new JsonObject();
        resultJson.addProperty("status", status);
        resultJson.addProperty("msg", meg);
        logger.info(gson.toJson(resultJson));
        return gson.toJson(resultJson);
    }

}
